﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Threading;
using System.Windows.Threading;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Composite.Presentation.Commands;
using Douban.Modules.Conversation.Views;
using Douban.Api.User;
using Douban.Api;
using Douban.Core;
using Douban.Modules.Conversation.Models;
using Douban.Api.Mail;
using System.Windows.Controls;
using System.Windows;
using System.Reflection;
using Douban.Core.Settings;

namespace Douban.Modules.Conversation.ViewModels
{
    public class ConversationWorkSpaceViewModel : ObservableObject, IConversationWorkSpaceViewModel
    {
        private const double RefreshReceiveMessageInterval = 60.0;
        private const double RefreshDisplayMessageInterval = 5.0;
        private readonly IUnityContainer _container;
        private readonly DoubanService _doubanService;
        private ICommand _sendMessageCommand;
        private string _content;
        private string _title;
        private DispatcherTimer _receiveMessageTimer;
        private DispatcherTimer _displayMessageTimer;
        private ICommand _clearMessageCommand;
        private ICommand _showOrCloseChatLogCommand;
        private ISettingManager _settingManager;
        private SendMessageHotKey _sendMessageHotKey;
        private bool _ctrlEnterToSendMessage;
        private bool _enterToSendMessage;

        public ConversationWorkSpaceViewModel(IConversationWorkSpaceView view, IUnityContainer container, 
            DoubanService doubanService, ISettingManager settingManager)
        {
            _container = container;
            _doubanService = doubanService;
            _settingManager = settingManager;
            DelayMessages = new Stack<MessageModel>();
            Messages = new ObservableCollection<MessageModel>();
            InitializeReceiveMessageTimer();
            InitializeDisplayReceivedMessageTimer();
            RegisterSendMessageHotKey();
            View = view;
            View.Context = this;
            View.SendMessageKeyDown += SendMessageKeyDown;
        }

        #region IConversationWorkSpaceViewModel Members

        public IConversationWorkSpaceView View { get; set; }

        public UserDetail User { get; set; }

        public UserDetail Contact { get; set; }

        public string Title
        {
            get
            {
                _title = User.Name + "   " + DateTime.Now.ToLongTimeString();
                return _title;
            }
        }

        public string Content
        {
            get { return _content; }
            set
            {
                if (_content != value)
                {
                    _content = value;
                    NotifyPropertyChanged("Content");
                }
            }
        }

        public ICommand SendMessageCommand
        {
            get
            {
                if (_sendMessageCommand == null)
                    _sendMessageCommand = new DelegateCommand<object>(obj => SendMessage());

                return _sendMessageCommand;
            }
        }

        public Stack<MessageModel> DelayMessages { get; set; }

        public ObservableCollection<MessageModel> Messages { get; set; }

        public ICaptchaViewModel CaptchaViewModel { get; set; }

        public ICommand ClearMessageCommand
        {
            get
            {
                if (_clearMessageCommand == null)
                    _clearMessageCommand = new DelegateCommand<object>(obj => ClearMessage());

                return _clearMessageCommand;
            }
        }

        public IChatLogViewModel ChatLogViewModel { get; set; }

        public ICommand ShowOrCloseChatLogCommand
        {
            get
            {
                if (_showOrCloseChatLogCommand == null)
                    _showOrCloseChatLogCommand = new DelegateCommand<object>(obj => OnChangeConversationShellToShowOrCloseChatLog());

                return _showOrCloseChatLogCommand;
            }
        }

        public event EventHandler ChangeConversationShellToShowOrCloseChatLog;

        public void Run()
        {
            ChatLogViewModel = _container.Resolve<IChatLogViewModel>();
            ChatLogViewModel.FileManager = new ChatLogFileManager(User.Id, Contact.Id);
            ChatLogViewModel.Run();
        }

        #endregion

        private void InitializeReceiveMessageTimer()
        {
            _receiveMessageTimer = new DispatcherTimer();
            _receiveMessageTimer.Interval = TimeSpan.FromSeconds(RefreshReceiveMessageInterval);
            _receiveMessageTimer.Tick += ReceiveMessageTimer_Tick;
            _receiveMessageTimer.Start();
        }

        private void ReceiveMessageTimer_Tick(object sender, EventArgs e)
        {
            Mailbox Inbox = _doubanService.MailService.GetMailbox(MailboxType.Inbox, true);

            if (Inbox.Messages == null) return;

            foreach (var message in Inbox.Messages)
            {
                if (message.Sender.Id == Contact.Id)
                {
                    MessageModel messageModel = new MessageModel();
                    messageModel.UserId = Contact.Id;
                    messageModel.Title = message.Title;
                    messageModel.Content = _doubanService.MailService.GetMail(message.Id).Content;
                    messageModel.IconUri = Contact.IconUri;

                    DelayMessages.Push(messageModel);
                }
            }
        }

        private void InitializeDisplayReceivedMessageTimer()
        {
            _displayMessageTimer = new DispatcherTimer();
            _displayMessageTimer.Interval = TimeSpan.FromSeconds(RefreshDisplayMessageInterval);
            _displayMessageTimer.Tick += DisplayReceivedMessageTimer_Tick;
            _displayMessageTimer.Start();
        }

        private void DisplayReceivedMessageTimer_Tick(object sender, EventArgs e)
        {
            if (DelayMessages.Count == 0) return;

            MessageModel message = DelayMessages.Pop();

            Messages.Add(message);

            View.SetMessageReaderScrollToBottom();

            ChatLogViewModel.TodayMessages.Add(message);

            ChatLogViewModel.FileManager.StoreChatLog(ChatLogViewModel.TodayMessages.ToArray(), DateTime.Now.ToString("yyyy-MM-dd"));
        }

        private void RegisterSendMessageHotKey()
        {
            _settingManager.Register("SendMessageHotKey", (name, value) =>
                {
                    _settingManager.Settings.SendMessageHotKey = (SendMessageHotKey)value;
                });
        }

        private void SendMessageKeyDown(object sender, KeyEventArgs e)
        {
            _sendMessageHotKey = _settingManager.Settings.SendMessageHotKey;

            _ctrlEnterToSendMessage = _sendMessageHotKey == SendMessageHotKey.CtrlEnter &&
                Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.Enter;

            _enterToSendMessage = _sendMessageHotKey == SendMessageHotKey.Enter && e.Key == Key.Enter;

            if (_ctrlEnterToSendMessage || _enterToSendMessage)
            {
                SendMessage();
            }
        }

        private void SendMessage()
        {
            if (String.IsNullOrEmpty(Content)) return;

            string captchaToken, captchaUrl;
            if (!_doubanService.MailService.TrySendMail(Contact.Id, Title, Content, out captchaToken, out captchaUrl))
            {
                CaptchaViewModel = _container.Resolve<ICaptchaViewModel>();
                CaptchaViewModel.CaptchaToken = captchaToken;
                CaptchaViewModel.CaptchaUrl = captchaUrl;
                CaptchaViewModel.SendCaptcha += SendCaptcha;
                CaptchaViewModel.View.ShowView();
            }

            if (CaptchaViewModel == null || CaptchaViewModel.CaptchaString != null)
            {
                SentMessageAddedToMessageCollection();

                View.SetMessageReaderScrollToBottom();
                View.ClearMessageSenderTextBox();
            }
        }

        private void SendCaptcha(object sender, EventArgs e)
        {
            _doubanService.MailService.SendMail(Contact.Id, Title, Content, CaptchaViewModel.CaptchaToken, CaptchaViewModel.CaptchaString);
        }

        private void SentMessageAddedToMessageCollection()
        {
            MessageModel messageModel = new MessageModel();
            messageModel.UserId = _doubanService.UserService.CurrentUser.Id;
            messageModel.Title = Title;
            messageModel.Content = Content;
            messageModel.IconUri = _doubanService.UserService.CurrentUser.IconUri;

            Messages.Add(messageModel);

            ChatLogViewModel.TodayMessages.Add(messageModel);

            ChatLogViewModel.FileManager.StoreChatLog(ChatLogViewModel.TodayMessages.ToArray(), DateTime.Now.ToString("yyyy-MM-dd"));
        }

        private void ClearMessage()
        {
            Messages.Clear();
        }

        private void OnChangeConversationShellToShowOrCloseChatLog()
        {
            if (ChangeConversationShellToShowOrCloseChatLog != null)
                ChangeConversationShellToShowOrCloseChatLog(this, new EventArgs());
        }
    }
}
